import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:qh_music/src/shared/constants/db.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
import 'package:path/path.dart' as path;

class SqliteStorage {
  static final SqliteStorage instance = SqliteStorage._();
  final String _dirName = 'databases';
  final int _version = 1;
  Database? db;
  final Logger _logger = Logger();

  SqliteStorage._();

  Future<void> init({String dbName = 'qh_music.db'}) async {
    if (db != null) {
      return;
    }
    if (kIsWeb) {
      _initWeb(dbName);
    } else if (Platform.isWindows || Platform.isLinux) {
      _initWindowOrLinux(dbName);
    }
    _initOther(dbName);
  }

  Future<void> _initOther(String dbName) async {
    db = await openDatabase(
      path.join(await _getDbDirPath(), dbName),
      version: _version,
      onCreate: _onCreate,
      onUpgrade: _onUpgrade,
      onOpen: _onOpen,
    );
  }

  Future<void> _initWeb(String dbName) async {
    databaseFactory = databaseFactoryFfiWeb;
    db = await databaseFactory.openDatabase(
      dbName,
      options: OpenDatabaseOptions(
        version: _version,
        onCreate: _onCreate,
        onUpgrade: _onUpgrade,
        onOpen: _onOpen,
      ),
    );
  }

  Future<void> _initWindowOrLinux(String dbName) async {
    sqfliteFfiInit();
    databaseFactory = databaseFactoryFfi;
    db = await databaseFactory.openDatabase(
      path.join(await _getDbDirPath(), dbName),
      options: OpenDatabaseOptions(
        version: _version,
        onCreate: _onCreate,
        onUpgrade: _onUpgrade,
        onOpen: _onOpen,
      ),
    );
  }

  FutureOr<void> _onCreate(Database database, int version) async {
    _logger.d('数据库创建:qh_music....');
    await database.execute(initSettingSql);
  }

  FutureOr<void> _onOpen(Database database) {
    _logger.d('数据库打开:qh_music....');
    db = database;
  }

  Future<void> closeDb() async {
    await db?.close();
    db = null;
  }

  FutureOr<void> _onUpgrade(
      Database database, int oldVersion, int newVersion) async {
    _logger.i('数据库更新:qh_music....$oldVersion -> $newVersion');
  }

  /// 获取数据库目录
  Future<String> _getDbDirPath() async {
    Directory appDocDir = await getApplicationDocumentsDirectory();
    String dirPath = path.join(appDocDir.path, _dirName);

    if (Platform.isAndroid) {
      dirPath = path.join(appDocDir.parent.path, _dirName);
    }
    if (Platform.isWindows || Platform.isLinux) {
      final PackageInfo packageInfo = await PackageInfo.fromPlatform();
      dirPath = path.join(appDocDir.path, packageInfo.appName, _dirName);
    }

    Directory result = Directory(dirPath);
    if (!result.existsSync()) {
      result.createSync(recursive: true);
    }
    return dirPath;
  }
}
